//============================================================================
// Name        : factory_method.cpp
// Author      : Tony Meng
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <memory>

// Factory method: using template

template< class ObjIf_ >
class FactoryIf
{
public:
	typedef ObjIf_ ObjIf;
	virtual ~FactoryIf() {}
	virtual ObjIf* createObj() const = 0;
};

template< class ObjType_, class ObjIf_ = ObjType_ >
class Factory : public FactoryIf< ObjIf_ >
{
public:
	typedef typename FactoryIf< ObjIf_ >::ObjIf ObjIf;
	typedef ObjType_                            ObjType;

	ObjIf* createObj() const
	{
		return new ObjType;
	}
};

class Car
{
public:
	virtual ~Car() {}
	virtual void drive() = 0;
};

class Bmw : public Car
{
public:
	void drive()
	{
		std::cout<<"Drive BMW."<<std::endl;
	}
};

class Saab : public Car
{
public:
	void drive()
	{
		std::cout<<"Drive SAAB."<<std::endl;
	}
};

typedef FactoryIf<Car> CarFactory;
static Car* createCarFromFactory(const CarFactory& carFactory)
{
	return carFactory.createObj();
}


int main() {
	const Factory<Bmw, Car> bmwFactory;
	const Factory<Saab, Car> saabFactory;

	std::auto_ptr<Car> aBmw(createCarFromFactory(bmwFactory));
	std::auto_ptr<Car> aSaab(createCarFromFactory(saabFactory));

	aBmw->drive();
	aSaab->drive();

	return 0;
}
